package com.wdciti.sccp.iot.position.model;

import lombok.Getter;
import lombok.Setter;

import java.util.*;

/**
 * 目前暂无毫秒以下高频采集业务，故timeStamp不考虑毫秒值重复的情况！
 */
@Getter
public class MeasureDataSet {

    @Setter
    private List<Long> timeStamps = new ArrayList<>();

    private final List<String> measureKeys;

    @Setter
    private Map<String, List<MeasureDataValue>> rawData = new HashMap<>();

    public MeasureDataSet(List<String> measureKeys) {
        this.measureKeys = measureKeys;
        this.rawData = new HashMap<>();
        for (String s : measureKeys) {
            this.rawData.put(s, new ArrayList<>());
        }
    }

    public List<MeasureDataValue> getDataSeries(String key) {
        return rawData.get(key);
    }


    public MeasureDataValue getDataValue(String key, long timeStamp) {
        int index = this.timeStamps.indexOf(timeStamp);
        List<MeasureDataValue> list = this.rawData.get(key);
        if (list == null || list.isEmpty()) {
            return new MeasureDataValue(timeStamp, key);
        } else {
            return list.get(index);
        }
    }

    public Map<String, MeasureDataValue> getAllDataValue(long timeStamp) {
        Map<String, MeasureDataValue> map = new HashMap<>(measureKeys.size());
        for (String key : measureKeys) {
            MeasureDataValue value = getDataValue(key, timeStamp);
            map.put(key, value);
        }
        return map;
    }

    public MeasureDataSet addDataValues(MeasureDataValue... values) {
        List<MeasureDataValue> list = Arrays.asList(values);
        return addDataValues(list);
    }

    public MeasureDataSet addDataValues(List<MeasureDataValue> values) {
        for (MeasureDataValue value : values) {
            if (!this.timeStamps.contains(value.getTimeStamp())) {
                this.timeStamps.add(value.getTimeStamp());
            }
            if (this.measureKeys.contains(value.getKey())) {
                this.rawData.get(value.getKey()).add(value);
            }
        }
        return this;
    }

    public void aligne() {
        List<Long> newTimeStamps = new ArrayList<>();
        Map<String, Map<Long, MeasureDataValue>> tmp = new HashMap<>();
        Map<String, List<MeasureDataValue>> newRawData = new HashMap<>(measureKeys.size());
        for (String key : measureKeys) {
            List<MeasureDataValue> values = rawData.get(key);
            if (values == null || values.isEmpty()) {
                continue;
            }
            for (MeasureDataValue value : values) { //按rawData时间点补齐
                if (!newTimeStamps.contains(value.getTimeStamp())) {
                    newTimeStamps.add(value.getTimeStamp());
                }
                tmp.getOrDefault(key, new HashMap<>()).put(value.getTimeStamp(), value);
            }
        }
        newTimeStamps.sort(Long::compareTo);
        //时间处理完了，开始处理值
        for (String key : measureKeys) {
            List<MeasureDataValue> newValueList = new ArrayList<>(newTimeStamps.size());    //定长数组
            newTimeStamps.forEach(aLong -> newValueList.add(new MeasureDataValue(aLong, key)));  //先空白填值。
            this.rawData.get(key).forEach(measureDataValue -> {
                int index = newTimeStamps.indexOf(measureDataValue.getTimeStamp()); //找出时间在新时间轴的位置。
                if (index >= 0) {    //填值
                    newValueList.get(index).setValue(measureDataValue.getValue(), measureDataValue.getDataType());
                }
            });
            newRawData.put(key, newValueList);
        }
//      替换
        this.timeStamps = newTimeStamps;
        this.rawData = newRawData;
    }


}
